#ifndef GX_FR_WORLD_EDITOR
#define GX_FR_WORLD_EDITOR

#include "Version.h"
#include "Windows/GxWinForm.h"
#include "Windows/GxWinApp.h"
#include "LibGL/GxUI.h"
#include "gl/gl.h"
#include "../resource.h"
#include "LibGL/OpenGL.h"
#include "ViewGrid.h"
#include "View.h"
#include "Editor.h"
#include "ToolBox.h"
#include "FileControl.h"
#include "MaterialDialog.h"
#include "OptionsDialog.h"
#include "PropertyEditor.h"
#include "MapCompile.h"
#include "Global.h"

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")

using namespace GxRendering;
using namespace GxRendering::UI;

using GxWinGUI::GLForm;
using GxWinGUI::Application;
using GxWinGUI::Timer;

namespace FinalRendering
{
	using namespace FinalRendering::Editor;

	class WorldEditorForm : public UIForm
	{
	private:
		Timer tmrUI;
		//RefPtr<UIEntry> ui;
		ToolButton * btnOpen, *btnSave, *btnUndo, *btnRedo, *btnRun;
		ToolStrip * toolBar;
		Menu * mainMenu;
		MenuItem * mnFile, *mnOpen, *mnSave, *mnSaveAs, *mnNew, *mnExit;
		MenuItem * mnEdit, *mnUndo, *mnRedo, *mnCut, *mnCopy, *mnPaste, *mnDelete, *mnSelectAll, *mnClearSelection, *mnFind;
		MenuItem * mnView, *mnCenterView, *mnSnapToGrid, *mnShowGrid, *mnGridSize, *mnGridSizeInc, *mnGridSizeDec;
		MenuItem * mnMap, *mnMapProperty, *mnCheckForProblems, *mnCompile, *mnRun;
		MenuItem * mnConstruct, *mnCSGSubtract, *mnMakeHollow, *mnGroup, *mnUnGroup;
		ViewGrid * viewGrid;
		StatusStrip * statusStrip;
		TabControl * tabSide;
		Label * lblCurMat;
		Button * btnTexcoordEdit;
		TextBox * txtTexTransX, * txtTexTransY, * txtTexScaleX, * txtTexScaleY, * txtTexRotAng, * txtTexLightmapScale;
		CheckBox * chkIgnore;
		Button * btnSelObj, *btnSelGroup, *btnGroup, *btnUnGroup;
		
		MaterialDialog * dlgMat;
		ComboBox * cmbCreateEntityClasses;
		RefPtr<PropertyEditor> propEditor;
		bool CanModifyTexcoord;
	public:
		WorldEditorForm()
		{
			Init();
		}

		~WorldEditorForm()
		{
			Finalize();
		}

		void Init()
		{
			OpenGL::Init();
			Global::Init();
			BeginGLDrawing();
			InitEditor((Form *)this, ui.operator->());
			InitUI();
			tmrUI.Interval = 50;
			tmrUI.StartTimer();
			tmrUI.OnTick.Bind(this, &WorldEditorForm::UITimerTick);
			WorldEditor->OnSelectionChanged.Bind(this, &WorldEditorForm::SelectionChanged);
			
		}

		void Finalize()
		{
			FinalizeEditor();
			Global::Finalize();
		}

		void InitUI()
		{
			SetText(GetEditorCaption());
			InitMenus();
			InitToolBar();
			InitView();
			InitStatusBar();
			InitSideBar();
			InitToolBox();
			dlgMat = new MaterialDialog();
		}

		void InitToolBox()
		{
			ToolBox * tb = new ToolBox();
			tb->DockStyle = Control::dsLeft;
			tb->SetWidth(40);
			ui->AddChild(tb);
		}

		void InitStatusBar()
		{
			statusStrip = new StatusStrip();
			statusStrip->SetHeight(24);
			statusStrip->DockStyle = Control::dsBottom;
			statusStrip->AddItem(new UI::StatusPanel(L"Ready",100,StatusPanel::Fill));
			ui->AddChild(statusStrip);
		}

		class MaterialView : public Control
		{
		public:
			void Draw(int absX, int absY)
			{
				BorderStyle = BS_LOWERED;
				Control::Draw(absX, absY);
				absX += Left;
				absY += Top + 1;
				if (WorldEditor->Scene->CurrentMaterial)
				{
					WorldEditor->Scene->CurrentMaterial->Bind();
					glColor4ub(255,255,255,255);
					glBegin(GL_QUADS);
					{
						glTexCoord2i(0,0);
						glVertex2i(absX, absY);
						glTexCoord2i(1,0);
						glVertex2i(absX+Width-2, absY);
						glTexCoord2i(1,1);
						glVertex2i(absX+Width-2, absY+Height-2);
						glTexCoord2i(0,1);
						glVertex2i(absX, absY+Height-2);
					}
					glEnd();
					glDisable(GL_TEXTURE_2D);
				}
				else
				{
					glDisable(GL_TEXTURE_2D);
					glColor4ub(255,255,255,255);
					glBegin(GL_QUADS);
					{
						glTexCoord2i(0,0);
						glVertex2i(absX, absY);
						glTexCoord2i(1,0);
						glVertex2i(absX+Width-2, absY);
						glTexCoord2i(1,1);
						glVertex2i(absX+Width-2, absY+Height-2);
						glTexCoord2i(0,1);
						glVertex2i(absX, absY+Height-2);
					}
					glEnd();
				}
			}
		};

		void InitSideBar()
		{
			tabSide = new TabControl();
			tabSide->DockStyle = Control::dsRight;
			tabSide->SetWidth(240);
			ui->AddChild(tabSide);

			Control * ctrl = new Control();
			ctrl->SetWidth(4);
			ctrl->BorderStyle = BS_FLAT;
			ctrl->BorderColor = Global::ColorTable->TabPageBorderColor;
			ctrl->DockStyle = Control::dsRight;
			ui->AddChild(ctrl);

			TabPage * pgCreate, *pgFace;
			pgCreate = new TabPage();
			pgCreate->SetImage(&Bitmap(IDB_CREATE), &Color());
			tabSide->AddItem(pgCreate);

			pgFace = new TabPage();
			pgFace->SetImage(&Bitmap(IDB_MATERIAL), &Color());
			tabSide->AddItem(pgFace);

			TitledPanel * pnlSel = new TitledPanel();
			pnlSel->SetText(L"Selection");
			pnlSel->SetHeight(200);
			pnlSel->DockStyle = Control::dsTop;
			pgCreate->AddChild(pnlSel);

			btnSelObj = new Button();
			btnSelGroup = new Button();
			btnGroup = new Button();
			btnUnGroup = new Button();
			btnSelObj->Posit(60,20, 120, 26);
			btnSelGroup->Posit(60, 50, 120, 26);
			btnGroup->Posit(60, 90, 120, 26);
			btnUnGroup->Posit(60, 120, 120, 26);
			
			pnlSel->AddChild(btnSelObj);
			pnlSel->AddChild(btnSelGroup);
			pnlSel->AddChild(btnGroup);
			pnlSel->AddChild(btnUnGroup);

			btnSelObj->SetText(L"Select Object");
			btnSelGroup->SetText(L"Select Group");
			btnGroup->SetText(L"&Group");
			btnUnGroup->SetText(L"&Ungroup");
			btnSelGroup->Checked = true;

			btnSelObj->OnClick.Bind(this, &WorldEditorForm::btnSelObjClicked);
			btnSelGroup->OnClick.Bind(this, &WorldEditorForm::btnSelGroupClicked);
			btnGroup->OnClick.Bind(this, &WorldEditorForm::btnGroupClicked);
			btnUnGroup->OnClick.Bind(this, &WorldEditorForm::btnUnGroupClicked);

			TitledPanel * pnlBrush = new TitledPanel();
			pnlBrush->SetText(L"Brush");
			pnlBrush->SetHeight(100);
			pnlBrush->DockStyle = Control::dsTop;
			pgCreate->AddChild(pnlBrush);
			
			Label * lblBrushType = new Label();
			lblBrushType->Posit(20,10, 80, 20);
			lblBrushType->SetText(L"Brush Type:");
			pnlBrush->AddChild(lblBrushType);
			
			ComboBox * cmbBrushType = new ComboBox();
			cmbBrushType->Posit(90, 8, 140,20);
			cmbBrushType->AddTextItem(L"Box");
			cmbBrushType->AddTextItem(L"Cylinder");
			cmbBrushType->AddTextItem(L"Cone");
			cmbBrushType->AddTextItem(L"Arc");
			cmbBrushType->SelectedIndex = 0;
			cmbBrushType->TextBox->SetText(L"Box");
			cmbBrushType->OnChanged.Bind(this, &WorldEditorForm::cmbBrushTypeChanged);
			pnlBrush->AddChild(cmbBrushType);

			IMETextBox * txtSides = new IMETextBox();
			txtSides->SetText(L"4");
			txtSides->Posit(90, 35, 123, 20);
			txtSides->OnChanged.Bind(this, &WorldEditorForm::txtSidesChanged);
			pnlBrush->AddChild(txtSides);

			UpDown * udSides = new UpDown(txtSides, 3.0f, 64.0f, 1.0f, 5.0f);
			udSides->Digits = 0;
			pnlBrush->AddChild(udSides);


			Label * lblSides = new Label();
			lblSides->Posit(20, 37, 80, 20);
			lblSides->SetText(L"Brush Sides:");
			pnlBrush->AddChild(lblSides);


			TitledPanel * pnlEntity = new TitledPanel();
			pnlEntity->SetText(L"Entity");
			pnlEntity->SetHeight(100);
			pnlEntity->DockStyle = Control::dsTop;
			pgCreate->AddChild(pnlEntity);

			cmbCreateEntityClasses = new ComboBox();
			cmbCreateEntityClasses->Posit(70,10,150,20);
			if (FinalRendering::Engine::Global->GetEntityPluginCount() > 0)
			{
				cmbCreateEntityClasses->TextBox->SetText(FinalRendering::Engine::Global->GetEntityDesc(0)->ClassName());
				WorldEditor->EntityClassName = cmbCreateEntityClasses->TextBox->GetText();
			}
			cmbCreateEntityClasses->OnChanged.Bind(this, &WorldEditorForm::cmbCreateEntityClasses_Changed);
			for (int i=0; i<FinalRendering::Engine::Global->GetEntityPluginCount(); i++)
				cmbCreateEntityClasses->AddTextItem(FinalRendering::Engine::Global->GetEntityDesc(i)->ClassName());
			pnlEntity->AddChild(cmbCreateEntityClasses);


			Label * lblEntClass = new Label();
			lblEntClass->SetText(L"Class:");
			lblEntClass->Posit(19,12,60,20);
			pnlEntity->AddChild(lblEntClass);

			TitledPanel * pnl = new TitledPanel();
			pnl->SetText(L"Material");
			pnl->SetHeight(300);
			pnl->DockStyle = Control::dsTop;
			pgFace->AddChild(pnl);

			lblCurMat = new Label();
			lblCurMat->Posit(20,10,20,20);
			lblCurMat->SetText(L"(none)");
			pnl->AddChild(lblCurMat);

			Button * btnBrowseMat = new Button();
			btnBrowseMat->SetText(L"Browse Material");
			btnBrowseMat->Posit(20,240,100,24);
			btnBrowseMat->OnClick.Bind(this, &WorldEditorForm::btnBrowseMatClicked);
			pnl->AddChild(btnBrowseMat);

			Button * btnApply = new Button();
			btnApply->SetText(L"Apply");
			btnApply->Posit(130,240,80,24);
			btnApply->OnClick.Bind(this, &WorldEditorForm::btnApplyClicked);
			pnl->AddChild(btnApply);

			MaterialView * matView = new MaterialView();
			matView->Posit(20, 30, 200,200);
			pnl->AddChild(matView);

			Label * lbl;

			UpDown * upd;

			pnl = new TitledPanel();
			pnl->SetText(L"Texture Coordinates");
			pnl->SetHeight(280);
			pnl->DockStyle = Control::dsTop;
			pgFace->AddChild(pnl);

			btnTexcoordEdit = new Button();
			btnTexcoordEdit->SetText(L"Edit Texcoord");
			btnTexcoordEdit->Posit(20,10,90, 24);
			btnTexcoordEdit->OnClick.Bind(this, &WorldEditorForm::btnTexcoordEditClicked);
			pnl->AddChild(btnTexcoordEdit);
			
			Button * btnTreatAsOne = new Button();
			btnTreatAsOne->SetText(L"Treat As One");
			btnTreatAsOne->Posit(120,10,90, 24);
			btnTreatAsOne->OnClick.Bind(this, &WorldEditorForm::btnTreatAsOneClicked);
			pnl->AddChild(btnTreatAsOne);

			int t = 40;

			lbl = new Label();
			lbl->Posit(20, 12+t, 100, 20);
			lbl->SetText(L"TransX:");
			pnl->AddChild(lbl);

			txtTexTransX = new TextBox();
			txtTexTransX->Posit(90, 10+t, 100, 20);
			txtTexTransX->OnChanged.Bind(this, &WorldEditorForm::TexcoordSystemChanged);
			pnl->AddChild(txtTexTransX);

			upd = new UpDown(txtTexTransX, -1024.0f, 1024.0f, 1.0f, 10.0f);
			upd->Digits = 0;
			pnl->AddChild(upd);

			lbl = new Label();
			lbl->Posit(20, 42+t, 100, 20);
			lbl->SetText(L"TransY:");
			pnl->AddChild(lbl);

			txtTexTransY = new TextBox();
			txtTexTransY->Posit(90, 40+t, 100, 20);
			txtTexTransY->OnChanged.Bind(this, &WorldEditorForm::TexcoordSystemChanged);
			pnl->AddChild(txtTexTransY);

			upd = new UpDown(txtTexTransY, -1024.0f, 1024.0f, 1.0f, 10.0f);
			upd->Digits = 0;
			pnl->AddChild(upd);

			lbl = new Label();
			lbl->Posit(20, 72+t, 100, 20);
			lbl->SetText(L"ScaleX:");
			pnl->AddChild(lbl);

			txtTexScaleX = new TextBox();
			txtTexScaleX->Posit(90, 70+t, 100, 20);
			txtTexScaleX->OnChanged.Bind(this, &WorldEditorForm::TexcoordSystemChanged);
			pnl->AddChild(txtTexScaleX); 

			upd = new UpDown(txtTexScaleX, -10.0f, 10.0f, 0.001f, 0.1f);
			pnl->AddChild(upd);

			lbl = new Label();
			lbl->Posit(20, 102+t, 100, 20);
			lbl->SetText(L"ScaleY:");
			pnl->AddChild(lbl);

			txtTexScaleY = new TextBox();
			txtTexScaleY->Posit(90, 100+t, 100, 20);
			txtTexScaleY->OnChanged.Bind(this, &WorldEditorForm::TexcoordSystemChanged);
			pnl->AddChild(txtTexScaleY);

			upd = new UpDown(txtTexScaleY, -10.0f, 10.0f, 0.001f, 0.1f);
			pnl->AddChild(upd);

			lbl = new Label();
			lbl->Posit(20, 132+t, 100, 20);
			lbl->SetText(L"Rotation:");
			pnl->AddChild(lbl);

			txtTexRotAng = new TextBox();
			txtTexRotAng->Posit(90, 130+t, 100, 20);
			txtTexRotAng->OnChanged.Bind(this, &WorldEditorForm::TexcoordSystemChanged);
			pnl->AddChild(txtTexRotAng);

			upd = new UpDown(txtTexRotAng, 0.0f, 360.0f, 1.0f, 60.0f);
			pnl->AddChild(upd);

			lbl = new Label();
			lbl->Posit(20, 160+t, 100, 20);
			lbl->SetText(L"Lightmap Resolution(unit/luxel):");
			pnl->AddChild(lbl);

			txtTexLightmapScale = new TextBox();
			txtTexLightmapScale->Posit(40, 180+t, 120, 20);
			txtTexLightmapScale->OnChanged.Bind(this, &WorldEditorForm::TexcoordSystemChanged);
			pnl->AddChild(txtTexLightmapScale);

			upd = new UpDown(txtTexLightmapScale, 1.0f, 256.0f, 1.0f, 16.0f);
			pnl->AddChild(upd);

			pnl = new TitledPanel();
			pnl->SetText(L"Brush");
			pnl->SetHeight(70);
			pnl->DockStyle = Control::dsTop;
			pgFace->AddChild(pnl);

			chkIgnore = new CheckBox();
			chkIgnore->SetText(L"Ignore");
			chkIgnore->Posit(20, 10, 120, 20);
			chkIgnore->BackColor.A = 0;
			chkIgnore->OnChanged.Bind(this, &WorldEditorForm::IgnoreCheckBox_Changed);
			pnl->AddChild(chkIgnore);

			TabPage * pgProperty = new TabPage();
			pgProperty->SetImage(&Bitmap(IDB_PROPERTY), &Color());
			tabSide->AddItem(pgProperty);
			propEditor = new PropertyEditor(pgProperty);
		}

		void InitView()
		{
			viewGrid = new ViewGrid();
			viewGrid->DockStyle = Control::dsFill;
			viewGrid->OnKeyDown.Bind(this, &WorldEditorForm::ViewKeyDown);
			ui->AddChild(viewGrid);
			WorldEditor->Views = viewGrid;
		}


		void InitMenus()
		{
			mainMenu = new Menu(Menu::msMainMenu);
			ui->AddChild(mainMenu);
			
			OnClose.Bind(this, &WorldEditorForm::FormClose);

			// File Menu
			mnFile = new MenuItem(L"&File");
			mainMenu->AddItem(mnFile);
			mnNew = new MenuItem(L"&New", L"Ctrl+N");
			mnNew->OnClick.Bind(this, &WorldEditorForm::mnNewClicked);
			mnFile->AddItem(mnNew);
			
			mnOpen = new MenuItem(L"&Open", L"Ctrl+O");
			mnOpen->OnClick.Bind(this, &WorldEditorForm::mnOpenClicked);

			mnFile->AddItem(mnOpen);
			mnSave = new MenuItem(L"&Save", L"Ctrl+S");
			mnSave->OnClick.Bind(this, &WorldEditorForm::mnSaveClicked);
			mnFile->AddItem(mnSave);

			mnSaveAs = new MenuItem(L"Save &As", L"Ctrl+Shift+S");
			mnSaveAs->OnClick.Bind(this, &WorldEditorForm::mnSaveAsClicked);
			mnFile->AddItem(mnSaveAs);

			mnFile->AddItem(new MenuItem());
			mnExit = new MenuItem(L"E&xit", L"Alt+F4");
			mnExit->OnClick.Bind(this, &WorldEditorForm::mnExitClicked);
			mnFile->AddItem(mnExit);

			// Edit Menu
			mnEdit = new MenuItem(L"&Edit");
			mainMenu->AddItem(mnEdit);
			mnUndo = new MenuItem(L"&Undo", L"Ctrl+Z");
			mnUndo->OnClick.Bind(this, &WorldEditorForm::mnUndoClicked);
			mnEdit->AddItem(mnUndo);

			mnRedo = new MenuItem(L"&Redo", L"Ctrl+Y");
			mnRedo->OnClick.Bind(this, &WorldEditorForm::mnRedoClicked);
			mnEdit->AddItem(mnRedo);

			mnEdit->AddItem(new MenuItem());

			mnCut = new MenuItem(L"Cu&t", L"Ctrl+X");
			mnCut->OnClick.Bind(this, &WorldEditorForm::mnCutClicked);
			mnEdit->AddItem(mnCut);

			mnCopy = new MenuItem(L"&Copy", L"Ctrl+C");
			mnCopy->OnClick.Bind(this, &WorldEditorForm::mnCopyClicked);
			mnEdit->AddItem(mnCopy);

			mnPaste = new MenuItem(L"&Paste", L"Ctrl+V");
			mnPaste->OnClick.Bind(this, &WorldEditorForm::mnPasteClicked);
			mnEdit->AddItem(mnPaste);

			mnDelete = new MenuItem(L"&Delete", L"Del");
			mnDelete->OnClick.Bind(this, &WorldEditorForm::mnDeleteClick);
			mnEdit->AddItem(mnDelete);

			mnEdit->AddItem(new MenuItem());

			mnClearSelection = new MenuItem(L"C&lear Selection", L"Ctrl+D");
			mnClearSelection->OnClick.Bind(this, &WorldEditorForm::mnClearSelectionClicked);
			mnEdit->AddItem(mnClearSelection);

			mnSelectAll = new MenuItem(L"&Select All", L"Ctrl+A");
			mnSelectAll->OnClick.Bind(this, &WorldEditorForm::mnSelectAllClicked);
			mnEdit->AddItem(mnSelectAll);
			mnEdit->AddItem(new MenuItem());
			mnFind = new MenuItem(L"&Find", L"Ctrl+F");
			mnEdit->AddItem(mnFind);

			// View Menu
			mnView = new MenuItem(L"&View");
			mainMenu->AddItem(mnView);
			mnShowGrid = new MenuItem(L"&Show Grid");
			mnView->AddItem(mnShowGrid);
			mnSnapToGrid = new MenuItem(L"S&nap to Grid");
			mnView->AddItem(mnSnapToGrid);
			mnGridSize = new MenuItem(L"&Grid Size");
			mnView->AddItem(mnGridSize);
			mnGridSizeInc = new MenuItem(L"Increase", L"[");
			mnGridSize->AddItem(mnGridSizeInc);
			mnGridSizeDec = new MenuItem(L"Decrease", L"]");
			mnGridSize->AddItem(mnGridSizeDec);
			mnView->AddItem(new MenuItem());
			mnCenterView = new MenuItem(L"&Center View On Selection", L"Ctrl+Shift+D");
			mnView->AddItem(mnCenterView);

			// Construct Menu
			mnConstruct = new MenuItem(L"&Construct");
			mainMenu->AddItem(mnConstruct);
			mnCSGSubtract = new MenuItem(L"CSG &Subtract", L"Ctrl+Shift+C");
			mnCSGSubtract->OnClick.Bind(this, &WorldEditorForm::mnCSGSubtractClicked);
			mnConstruct->AddItem(mnCSGSubtract);
			mnMakeHollow = new MenuItem(L"Make &Hollow", L"Ctrl+Shift+H");
			mnMakeHollow->OnClick.Bind(this, &WorldEditorForm::mnMakeHollowClicked);
			mnConstruct->AddItem(mnMakeHollow);
			mnConstruct->AddItem(new MenuItem());
			mnGroup = new MenuItem(L"&Group", L"Ctrl+G");
			mnConstruct->AddItem(mnGroup);
			mnUnGroup = new MenuItem(L"&Ungroup", L"Ctrl+B");
			mnConstruct->AddItem(mnUnGroup);

			// Map Menu
			mnMap = new MenuItem(L"&Map");
			mainMenu->AddItem(mnMap);
			mnCompile = new MenuItem(L"&Compile", L"F7");
			mnCompile->OnClick.Bind(this, &WorldEditorForm::mnCompileClicked);
			mnMap->AddItem(mnCompile);
			mnRun = new MenuItem(L"&Run", L"F5");
			mnMap->AddItem(mnRun);
			mnMap->AddItem(new MenuItem());
			mnCheckForProblems = new MenuItem(L"Check for &Problems", L"F9");
			mnMap->AddItem(mnCheckForProblems);
			mnMap->AddItem(new MenuItem());
			mnMapProperty = new MenuItem(L"Map &Properties");
			mnMap->AddItem(mnMapProperty);
		
			MenuItem * mnTools = new MenuItem(L"&Tools");
			mainMenu->AddItem(mnTools);
			MenuItem * mnOptions = new MenuItem(L"&Options");
			mnOptions->OnClick.Bind(this, &WorldEditorForm::mnOptionsClicked);
			mnTools->AddItem(mnOptions);

		}

		void InitToolBar()
		{
			toolBar = new ToolStrip();
			ui->AddChild(toolBar);
			btnOpen = toolBar->AddButton(String(L"Open"), &Bitmap(IDB_OPEN));
			btnSave = toolBar->AddButton(L"Save", &Bitmap(IDB_SAVE));
			toolBar->AddSeperator();
			btnUndo = toolBar->AddButton(L"Undo", &Bitmap(IDB_UNDO));
			btnRedo = toolBar->AddButton(L"Redo", &Bitmap(IDB_REDO));
		}

		void UITimerTick(Object * sender, GxWinGUI::EventArgs e)
		{
			if (this->Focused() && viewGrid->ContainsFocus())
			{
				HandleCameraKeys();
				BeginGLDrawing();
				WorldEditor->UpdateViews();
				Refresh();
			}
		}

		void HandleCameraKeys()
		{
			static LARGE_INTEGER lastTime, curTime, freq;
			static float dspeed = 0.0f;
			static float lspeed = 0.0f;

			QueryPerformanceCounter(&curTime);
			QueryPerformanceFrequency(&freq);

			float dtime = (curTime.QuadPart-lastTime.QuadPart)/(float)(freq.QuadPart);
			if (dtime < 0.0f)
				dtime = 0.1f;
			else if (dtime > 0.5f)
				dtime = 0.5f;

			lastTime = curTime;

			if (viewGrid->ContainsFocus() && Focused())
			{
				if (GetAsyncKeyState(L'W') != 0)
				{
					if (dspeed < WorldEditor->Preference.CameraMinSpeed)
						dspeed = WorldEditor->Preference.CameraMinSpeed;
					else
					{
						dspeed += WorldEditor->Preference.CameraAcceleration*dtime;
						if (dspeed > WorldEditor->Preference.CameraMaxSpeed)
							dspeed = WorldEditor->Preference.CameraMaxSpeed;
					}
				}
				else if (GetAsyncKeyState(L'S') != 0)
				{
					if (dspeed > -WorldEditor->Preference.CameraMinSpeed)
						dspeed = -WorldEditor->Preference.CameraMinSpeed;
					else
					{
						dspeed -= WorldEditor->Preference.CameraAcceleration*dtime;
						if (dspeed < -WorldEditor->Preference.CameraMaxSpeed)
							dspeed = -WorldEditor->Preference.CameraMaxSpeed;
					}
				}
				else
					dspeed = 0.0f;
				if (GetAsyncKeyState(L'A') != 0)
				{
					if (lspeed < WorldEditor->Preference.CameraMinSpeed)
						lspeed = WorldEditor->Preference.CameraMinSpeed;
					else
					{
						lspeed += WorldEditor->Preference.CameraAcceleration*dtime;
						if (lspeed > WorldEditor->Preference.CameraMaxSpeed)
							lspeed = WorldEditor->Preference.CameraMaxSpeed;
					}
				}
				else if (GetAsyncKeyState(L'D') != 0)
				{
					if (lspeed > -WorldEditor->Preference.CameraMinSpeed)
						lspeed = -WorldEditor->Preference.CameraMinSpeed;
					else
					{
						lspeed -= WorldEditor->Preference.CameraAcceleration*dtime;
						if (lspeed < -WorldEditor->Preference.CameraMaxSpeed)
							lspeed = -WorldEditor->Preference.CameraMaxSpeed;
					}
				}
				else
					lspeed = 0.0f;

				float lturn = 0.0f;
				float uturn = 0.0f;
				if (GetAsyncKeyState(VK_LEFT))
				{
					lturn = WorldEditor->Preference.CameraTurnAngle * dtime;
				}
				if (GetAsyncKeyState(VK_RIGHT))
				{
					lturn = -WorldEditor->Preference.CameraTurnAngle * dtime;
				}

				if (GetAsyncKeyState(VK_UP))
				{
					uturn = WorldEditor->Preference.CameraTurnAngle * dtime;
				}
				if (GetAsyncKeyState(VK_DOWN))
				{
					uturn = -WorldEditor->Preference.CameraTurnAngle * dtime;
				}

				for (int i=0; i<4; i++)
				{
					if (viewGrid->SceneViews[i]->Type == View::vtPerspective)
					{
						View3D * view = (View3D *)viewGrid->SceneViews[i].operator ->();
						view->cam.MoveLeft(lspeed*dtime);
						view->cam.GoForward(dspeed*dtime);
						view->cam.TurnLeft(lturn);
						view->cam.TurnUp(uturn);
						view->Refresh();
					}	
				}

			}
		}

		void cmbCreateEntityClasses_Changed(UI_Base * sender)
		{
			WorldEditor->EntityClassName = cmbCreateEntityClasses->GetTextItem(cmbCreateEntityClasses->SelectedIndex)->GetText();
		}

		void SelectionChanged()
		{
			propEditor->SelectionChanged();
			if (!WorldEditor->Selection.Count())
				return;
			CanModifyTexcoord = false;
			Selection & sel = WorldEditor->Selection[0];
			
			if (!WorldEditor->EditTexcoord)
			{
				if (sel.Type == Selection::otBrush)
					chkIgnore->Checked = WorldEditor->Scene->Brushes[sel.ID]->Polygons[0].Ignore;
			}
			else
			{
				if (sel.Type == Selection::otBrush)
				{
					chkIgnore->Checked = WorldEditor->Scene->Brushes[sel.ID]->Polygons[sel.SecondaryID].Ignore;
					Polygon & p = WorldEditor->Scene->Brushes[sel.ID]->Polygons[sel.SecondaryID];
					txtTexScaleX->SetText(p.TexcoordSystem.ScaleX);
					txtTexScaleY->SetText(p.TexcoordSystem.ScaleY);
					txtTexTransX->SetText(p.TexcoordSystem.TransX);
					txtTexTransY->SetText(p.TexcoordSystem.TransY);
					txtTexRotAng->SetText(p.TexcoordSystem.RotAng);
					txtTexLightmapScale->SetText(p.TexcoordSystem.LightmapScale);
				}
			}
			CanModifyTexcoord = true;
			
		}

		void IgnoreCheckBox_Changed(UI_Base * sender)
		{
			if (!CanModifyTexcoord)
				return;
			WorldEditor->SetBrushFlag(((CheckBox*)sender)->Checked);
		}

		void btnApplyClicked(UI_Base * sender)
		{
			for (int i=0; i<WorldEditor->Selection.Count(); i++)
			{
				int id = WorldEditor->Selection[i].ID;
				int id2 = WorldEditor->Selection[i].SecondaryID;
				Brush & b = *(WorldEditor->Scene->Brushes[id]);
				if (WorldEditor->EditTexcoord)
				{
					Polygon & p = b.Polygons[id2];
					p.Material = WorldEditor->Scene->CurrentMaterial;
					p.MatName = WorldEditor->Scene->CurrentMaterialName;
				}
				else
				{
					for (int j=0; j<b.Polygons.Count(); j++)
					{
						b.Polygons[j].Material = WorldEditor->Scene->CurrentMaterial;
						b.Polygons[j].MatName = WorldEditor->Scene->CurrentMaterialName;
					}
				}
			}

			WorldEditor->UpdateViews();
		}

		void mnCompileClicked(UI_Base * sender)
		{
			CompileMap();
		}

		void btnTexcoordEditClicked(UI_Base * sender)
		{
			btnTexcoordEdit->Checked = !btnTexcoordEdit->Checked;
			WorldEditor->EditTexcoord = btnTexcoordEdit->Checked;
			WorldEditor->CancelSelection();
		}

		void mnDeleteClick(UI_Base * sender)
		{
			WorldEditor->Delete();
		}

		void mnOpenClicked(UI_Base * sender)
		{
			WorldEditor->Open();
		}

		void mnSaveClicked(UI_Base * sender)
		{
			WorldEditor->Save();
		}

		void mnSaveAsClicked(UI_Base * sender)
		{
			WorldEditor->SaveAs();
		}

		void mnNewClicked(UI_Base * sender)
		{
			WorldEditor->New();
		}

		void mnExitClicked(UI_Base * sender)
		{
			Close();
		}

		void mnUndoClicked(UI_Base * sender)
		{
			WorldEditor->Undo();
		}

		void mnRedoClicked(UI_Base * sender)
		{
			WorldEditor->Redo();
		}

		void mnCutClicked(UI_Base * sender)
		{
			WorldEditor->Cut();
		}

		void mnCopyClicked(UI_Base * sender)
		{
			WorldEditor->Copy();
		}

		void mnPasteClicked(UI_Base * sender)
		{
			WorldEditor->Paste();
		}

		void mnSelectAllClicked(UI_Base * sender)
		{
			WorldEditor->SelectAll();
		}

		void mnClearSelectionClicked(UI_Base * sender)
		{
			WorldEditor->CancelSelection();
		}

		void mnMakeHollowClicked(UI_Base * sender)
		{
			WorldEditor->MakeHollow();
		}

		void mnOptionsClicked(UI_Base * sender)
		{
			RefPtr<OptionsDialog> dlg = new OptionsDialog();
			dlg->ShowModal(this);

		}

		void mnCSGSubtractClicked(UI_Base * sender)
		{
			WorldEditor->Carve();
		}

		void btnTreatAsOneClicked(UI_Base * sender)
		{
			WorldEditor->TextureAdjust_TreatAsOne();
		}

		void btnSelObjClicked(UI_Base * sender)
		{
			btnSelGroup->Checked = false;
			btnSelObj->Checked = true;
			WorldEditor->SelectMode = WorldEditorSingleton::smObject;
		}

		void btnSelGroupClicked(UI_Base * sender)
		{
			btnSelGroup->Checked = true;
			btnSelObj->Checked = false;
			WorldEditor->SelectMode = WorldEditorSingleton::smGroup;
		}

		void btnGroupClicked(UI_Base * sender)
		{
			WorldEditor->Group();
		}

		void btnUnGroupClicked(UI_Base * sender)
		{
			WorldEditor->Ungroup();
		}

		void cmbBrushTypeChanged(UI_Base * sender)
		{
			ComboBox * b = (ComboBox*)sender;
			WorldEditor->BrushType = (WorldEditorSingleton::_BrushType)b->SelectedIndex;
		}

		void txtSidesChanged(UI_Base * sender)
		{
			TextBox * txt = (TextBox *)sender;
			WorldEditor->BrushEdges = txt->GetText().ToInt();
			if (WorldEditor->BrushEdges < 3)
				WorldEditor->BrushEdges = 3;
			if (WorldEditor->BrushEdges > 64)
				WorldEditor->BrushEdges = 64;
		}

		void btnBrowseMatClicked(UI_Base * sender)
		{
			if (dlgMat->ShowModal(this)==BaseForm::OK)
			{
				RefPtr<EditorMaterial> mat = WorldEditor->Scene->LoadMaterial(dlgMat->FileName);
				if (mat)
				{
					WorldEditor->Scene->CurrentMaterial = mat;
					WorldEditor->Scene->CurrentMaterialName = dlgMat->FileName;
					lblCurMat->SetText(dlgMat->FileName);
					
					btnApplyClicked(sender);
				}
			}
		}

		void TexcoordSystemChanged(UI_Base * sender)
		{

			if (WorldEditor->EditTexcoord && CanModifyTexcoord)
			{
				for (int i=0; i<WorldEditor->Selection.Count(); i++)
				{
					int id, id2;
					id = WorldEditor->Selection[i].ID;
					id2 = WorldEditor->Selection[i].SecondaryID;
					if (WorldEditor->Selection[i].Type == Selection::otBrush)
					{
						Polygon & p = WorldEditor->Scene->Brushes[id]->Polygons[id2];
						if (sender == txtTexScaleX)
							p.TexcoordSystem.ScaleX = txtTexScaleX->GetText().ToFloat();
						if (sender == txtTexScaleY)
							p.TexcoordSystem.ScaleY = txtTexScaleY->GetText().ToFloat();
						if (sender == txtTexTransX)
							p.TexcoordSystem.TransX = txtTexTransX->GetText().ToFloat();
						if (sender == txtTexTransY)
							p.TexcoordSystem.TransY = txtTexTransY->GetText().ToFloat();
						if (sender == txtTexRotAng)
							p.TexcoordSystem.RotAng = txtTexRotAng->GetText().ToFloat();
						if (sender == txtTexLightmapScale)
							p.TexcoordSystem.LightmapScale = txtTexLightmapScale->GetText().ToFloat();
					}
					WorldEditor->Scene->Brushes[id]->GeneratePolygonTexcoord();
				}
				WorldEditor->UpdateViews();
			}
		}

		void FormClose(Object * sender, GxWinGUI::WindowCloseEventArgs & e)
		{
			if (!WorldEditor->Close())
				e.Cancel = true;
		}

		void ViewKeyDown(UI_Base * sender, UIKeyEventArgs & e)
		{
			if (e.Shift == SS_CONTROL)
			{
				switch (e.Key)
				{
				case L'N':
					WorldEditor->New();
					break;
				case L'S':
					WorldEditor->Save();
					break;
				case L'O':
					WorldEditor->Open();
					break;
				}
			}
			else if (e.Shift == (SS_CONTROL|SS_SHIFT))
			{
				switch (e.Key)
				{
				case L'S':
					WorldEditor->SaveAs();
					break;
				case L'C':
					WorldEditor->Carve();
					break;
				case L'H':
					WorldEditor->MakeHollow();
					break;
				}
			}
		}

		
	};

}
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
	Application::Init(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
	
	Application::Run(new FinalRendering::WorldEditorForm());
	Application::Dispose();
	return 1;
}

#endif